#ifndef __AVR_ATmega16__
#define __AVR_ATmega16__
#endif
#ifndef F_CPU
#define F_CPU 8000000
#endif
#define BAUD 9600

#define refresh(x) (F_CPU / 256 / (x))
//port 3 untusk titik
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <util/setbaud.h>
#include <util/delay.h>
#include <util/twi.h>


#define char_o 23
#define char_O 231
#define char_k 117
#define char_l 35
#define char_min 16
static unsigned char angka[10] = {231,132,211,214,180,118,119,196,247,246};
volatile unsigned char rat;
volatile unsigned char pul;
volatile unsigned char sat;

volatile char debug =0;
/*
void zero_cross();
void trigger_triac();
void adc_updt();
*/
unsigned char send_spi(unsigned char);
int send (char,FILE *);
int receive (FILE*);
int main(void){
    unsigned int adc;
    int hasil;
    unsigned char count = 0;
    unsigned char data;
    //unsigned char count=0;
    float suhu;
    //inisialisasi
    SFIOR = ~_BV(PUD);//enable pull up; dipakai oleh int1
    sei();//SREG_I_bit = 1;//enable interrupt

    //refresh timer 1
    TCCR1A = 0;
    TCCR1B = _BV(CS12) | _BV(WGM12);
    OCR1A = refresh(333);
    OCR1B = refresh(333);

    //UART
    UBRRL = UBRRL_VALUE;
    UBRRH = UBRRH_VALUE;
    UCSRB = _BV(TXEN) | _BV(RXEN) | _BV(RXCIE);
    UCSRC = ((_BV(URSEL) & ~(_BV(UMSEL)) & ~(_BV(UPM0)) & ~(_BV(UPM1)) & ~(_BV(USBS)))  | _BV(UCSZ1) | _BV(UCSZ0)) & ~(_BV(UCPOL));
    fdevopen(send,receive);
    printf("Hello world\n");
    
    //seven segment cc
    DDRC = 0xFF;//output buat seven seg
    DDRD = _BV(DDD4) | _BV(DD5) | _BV(DD6);//pin scan 7seg
    PORTD = _BV(PD4);
   
    //SPI
    DDRB = _BV(PB4) | _BV(PB5) | _BV(PB7);
    PORTB &= ~_BV(PB4);
    SPCR = _BV(MSTR) | _BV(SPE) | _BV(SPR0) | _BV(SPR1);
    _delay_ms(2000);
    PORTB |= _BV(PORTB4);
    if(debug){
        goto debugg;
    }
    
    //ADC Maxim
    //data = DRDY | RS2 | RS1 | RS0 | R/W' | PD | CH1 | Ch0
    //setting clock register
    send_spi(0b00100000);//want to write clock reg,32
    send_spi(0b10100100);//internal clock,50Hz filter,164
    send_spi(0b00101000);//want to read clock,40
    data = send_spi(0);
    if(data == 0b10100100){
        TIMSK = _BV(OCIE1B);
    }
    _delay_ms(500);
    send_spi(0x10);//16
    send_spi(0b01011100);//start calib+conv,94
    TIMSK =  _BV(OCIE1A);
    do{
        do{
            send_spi(0x08);//8
            data = send_spi(0x0);
        }while(data & 0b10000000);//80
        send_spi(0x38);//56
        adc = send_spi(10) << 8;//0
        adc += (unsigned int) send_spi(4);//4
        suhu = (adc * 300ul) / 65535e0;
        if (adc >= 100 * (65536 / 300)){
            suhu *= -23.1e-9;
            suhu += 17.58480889e-6;
            suhu = sqrt(suhu);
            suhu += -3.9083e-3;
            suhu /= -1.155e-6;
            adc = suhu;
            rat = angka[(adc % 1000) / 100];
            pul = angka[(adc % 100) / 10];
            sat = angka[adc % 10];
        }else{
            suhu = -242.02 + 2222.8 * suhu + 2.5859e-3 * pow(suhu,2) - 4.8260e-6 * pow(suhu,3) -2.8183e-8 * pow(suhu,4) + 1.5243e-10 * pow(suhu,5);
            hasil = abs(suhu);
            rat = char_min;
            pul = angka[(hasil % 100) / 10];
            sat = angka[hasil % 10];
        }
        if((++count) == 0){
            send_spi(0b00101000);//want to read clock,40
            data = send_spi(0);
            if(data != 0b10100100){
                TIMSK = 0;
                send_spi(0xFF);
                send_spi(0xFF);
                send_spi(0xFF);
                send_spi(0xFF);
                send_spi(0b00101000);//want to read clock,40
                data = send_spi(0);
                if(data == 0b10100100){
                    TIMSK = _BV(OCIE1B);
                    _delay_ms(500);
                    //TIMSK = _BV(OCIE1A);
                }
                TIMSK = _BV(OCIE1A);
            }
            //TIMSK = _BV(OCIE1A);
        }
    }while(1);
debugg:
    UCSRB &= ~_BV(RXCIE);
    unsigned char dummy;
    while ( UCSRA & (1<<RXC) ) dummy = UDR;
    printf("Debug mode\n");
    do{
        while ( UCSRA & (1<<RXC) ) dummy = UDR;
        scanf("%d", &adc);
        printf("data out=%x %d\n",adc,adc);
        data = adc;
        rat = send_spi(data);
        printf("data in=%x %d\n",rat,rat);
    }while(1);
    return 0;
}

unsigned char send_spi(unsigned char data){
    SPDR = data;
    do {} while (!(SPSR & _BV(SPIF)));
    return SPDR;
}
ISR(TIMER1_COMPA_vect){
    if(PORTD & _BV(PD6)){
        PORTD &= ~_BV(PORTD6);
        PORTD |= _BV(PORTD4);
        PORTC = rat;
    }else if(PORTD & _BV(PD4)){
        PORTD &= ~_BV(PORTD4);
        PORTD |= _BV(PORTD5);
        PORTC = pul;
    }else if(PORTD & _BV(PD5)){
        PORTD &= ~_BV(PORTD5);
        PORTD |= _BV(PORTD6);
        PORTC = sat;
    }
}
ISR(TIMER1_COMPB_vect){
    if(PORTD & _BV(PD5)){
        PORTD &= ~_BV(PORTD5);
        PORTD |= _BV(PORTD4);
        PORTC = char_O;
    }else if(PORTD & _BV(PD4)){
        PORTD &= ~_BV(PORTD4);
        PORTD |= _BV(PORTD5);
        PORTC = char_l;
    }
}

ISR(USART_RXC_vect){
    char x = UDR;
    if (x == 'd'){
        debug =1;
    }
}

int send(char ch, FILE * f){
    if (ch == '\n')
        send('\r',0);
    loop_until_bit_is_set(UCSRA, UDRE);
    UDR = ch;
    return 0;

    //bip();
}

int receive (FILE* f){
    unsigned char status, resl;
    /* Wait for data to be received */
    while ( !(UCSRA & (1<<RXC)) );
    /* Get status and 9th bit, then data */
    /* from buffer */
    status = UCSRA;
    resl = UDR;
    /* If error, return -1 */
    if ( status & ((1<<FE)|(1<<DOR)|(1<<PE)))
    return -1;
    if(resl == '\n'){
        return 0;
    }
    /* Filter the 9th bit, then return */
    return resl;
}